package com.winit.feature.web;


import com.winit.common.base.bean.ExecuteResult;
import com.winit.common.base.web.BaseController;
import com.winit.common.util.Constants;
import com.winit.feature.manager.FeatureManager;
import com.winit.feature.model.Feature;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpStatus;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@RestController
@Api(value = "feature", tags = {"feature"}, description = "feature")
@RequestMapping(value = "/api/v1/feature")
public class FeatureController extends BaseController {

    private static Logger logger = LoggerFactory.getLogger(FeatureController.class);

    @Autowired
    private FeatureManager featureManager;

//    @Autowired
//    private FeatureManager_bak featureManager_bak;

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取menu + page tree")
    @RequestMapping(value = "/getFeatureBaseTree", method = RequestMethod.GET)
    @ResponseBody
//    @Cacheable(cacheNames = {"tree_feature"}, key = "#reqId  + '-' +  #sys + '-' + #featureId + '-' + #withChildren + '-' + #withAttrs")
    @Cacheable(cacheNames = {"feature_base_tree"}, key = "#sys")
    public Map getFeatureBaseTree( @ApiParam(value = "sys，所属系统('tom','sellerportal')", required = true) @RequestParam(value = "featureSys", required = true) String sys,
                              @ApiParam(value = "menuId，唯一标志；查询一个功能点信息", required = false) @RequestParam(value = "menuId", required = false) String menuId) {
        if (!StringUtils.isEmpty(sys)){
            sys = sys.toUpperCase();
        }
        System.out.println("xxxx=========================================================");
        return this.getRtn("0", "success", this.featureManager.getFeatureBaseTree(sys, menuId));
    }


    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取page关联的feature（不返回attr）")
    @RequestMapping(value = "/getPageFeatures", method = RequestMethod.GET)
    @ResponseBody
//    @Cacheable(cacheNames = {"tree_feature"}, key = "#reqId  + '-' +  #sys + '-' + #featureId + '-' + #withChildren + '-' + #withAttrs")
    public Map getPageFeatures( @ApiParam(value = "pageId", required = false) @RequestParam(value = "pageId", required = true) String pageId) {
        return this.getRtn("0", "success", this.featureManager.getPageFeatures(pageId));
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取feature")
    @RequestMapping(value = "/getFeature", method = RequestMethod.GET)
    @ResponseBody
//    @Cacheable(cacheNames = {"tree_feature"}, key = "#reqId  + '-' +  #sys + '-' + #featureId + '-' + #withChildren + '-' + #withAttrs")
    public Map getFeature( @ApiParam(value = "id", required = false) @RequestParam(value = "id", required = false) String id,
                           @ApiParam(value = "sys", required = false) @RequestParam(value = "sys", required = false) String sys,
                           @ApiParam(value = "reqId,为空时查询所有功能点，不为空时按req查询", required = false) @RequestParam(value = "reqId", required = false) String reqId,
                           @ApiParam(value = "path", required = false) @RequestParam(value = "path", required = false) String path,
                           @ApiParam(value = "withPrototype, 是否包含prototype的feature 0-否，1-是，缺省为1", required = false) @RequestParam(value = "withPrototype", defaultValue = "1") String withPrototype,
                           @ApiParam(value = "withAttr", required = false) @RequestParam(value = "withAttr", required = false, defaultValue = "0") String withAttr) {
        if(!StringUtils.isEmpty(sys)){
            sys = sys.toUpperCase();
        }
        ExecuteResult executeResult = this.featureManager.getFeature(id, sys, reqId, path, withAttr, withPrototype);
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }

//    @ResponseStatus(HttpStatus.OK)
//    @ApiOperation(value = "将feature关联至指定page")
//    @RequestMapping(value = "/relateToPage", method = RequestMethod.GET)
//    @ResponseBody
//////    @Cacheable(cacheNames = {"tree_feature"}, key = "#reqId  + '-' +  #sys + '-' + #featureId + '-' + #withChildren + '-' + #withAttrs")
//    public Map relateToPage( @ApiParam(value = "reqId", required = true) @RequestParam(value = "reqId", required = true) String reqId,
//                            @ApiParam(value = "featureId", required = true) @RequestParam(value = "featureId", required = true) String featureId,
//                           @ApiParam(value = "pageId", required = true) @RequestParam(value = "pageId", required = true) String pageId){
//        ExecuteResult executeResult = this.featureManager.relateToPage(reqId, featureId, pageId);
//        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
//    }


    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "创建功能点")
    @RequestMapping(value = "/createFeature", method = RequestMethod.POST)
    @ResponseBody
//    @Cacheable(cacheNames = {"tree_feature"}, key = "#reqId  + '-' +  #sys + '-' + #featureId + '-' + #withChildren + '-' + #withAttrs")
    public Map createFeature(@RequestBody Feature feature) {
        ExecuteResult executeResult = this.featureManager.createFeature(feature);
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "修改功能点的attr")
    @RequestMapping(value = "/updateFeatureAttrForReq", method = RequestMethod.POST)
    @ResponseBody
//    @Cacheable(cacheNames = {"tree_feature"}, key = "#reqId  + '-' +  #sys + '-' + #featureId + '-' + #withChildren + '-' + #withAttrs")
    public Map updateFeatureAttrForReq(@RequestBody Feature feature) {
        Assert.isTrue(!StringUtils.isEmpty(feature.getId()), "id必填");
        Assert.isTrue(!StringUtils.isEmpty(feature.getReqId()), "reqId必填");
        Assert.isTrue(!StringUtils.isEmpty(feature.getAttr()), "attr必填");
        ExecuteResult executeResult = this.featureManager.updateFeatureAttrForReq(feature.getId(), feature.getReqId(), feature.getAttr());
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "更新master feature")
    @RequestMapping(value = "/updateFeature", method = RequestMethod.POST)
    @ResponseBody
//    @CacheEvict(cacheNames = {"tree_feature"}, allEntries = true)
    public Map updateFeature(@RequestBody Feature feature) {
        Assert.isTrue(!StringUtils.isEmpty(feature.getId()), "feature id不能为空");
        /** 后续可以考虑放宽（去掉）这个校验 */
        if ((null != feature.getReqId()) && (!Constants.FEATURE_ROOT_REQ_ID.equals(feature.getReqId()))) {
            return this.getRtn(BaseController.REQUEST_ERROR, "reqId只能为-1或者null");
        }
        if(!StringUtils.isEmpty(feature.getSys())){
            feature.setSys(feature.getSys().toUpperCase());
        }
        ExecuteResult executeResult = this.featureManager.updateFeature(feature);
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "删除属于req的feature与page的对应关系")
    @RequestMapping(value = "/dissociateRelation", method = RequestMethod.GET)
    @ResponseBody
//    @CacheEvict(cacheNames = {"tree_feature"}, allEntries = true)
    public Map dissociateRelation(@ApiParam(value = "reqId", required = true) @RequestParam(value = "reqId", required = true, defaultValue = "-1") String reqId,
                                  @ApiParam(value = "featureId", required = true) @RequestParam(value = "featureId", required = true) String featureId) {
        ExecuteResult executeResult = this.featureManager.dissociateRelation(reqId, featureId);
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }




    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "物理删除feature以及与之相关的关系")
    @RequestMapping(value = "/deleteFeature", method = RequestMethod.GET)
    @ResponseBody
    public Map deleteFeature(@ApiParam(value = "featureId", required = true) @RequestParam(value = "featureId", required = true) String featureId) {
        ExecuteResult executeResult = this.featureManager.deleteFeature(featureId);
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "req占用功能点")
    @RequestMapping(value = "/featureOccupy", method = RequestMethod.GET)
    @ResponseBody
//    @CacheEvict(cacheNames = {"tree_feature"}, allEntries = true)
    public Map featureOccupy(@ApiParam(value = "reqId", required = false) @RequestParam(value = "reqId", required = true) String reqId,
                             @ApiParam(value = "feature表中的id", required = false) @RequestParam(value = "id", required = true) String id) {

        ExecuteResult executeResult = this.featureManager.featureOccupy(reqId, id);
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }




    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取req关联的feature信息列表")
    @RequestMapping(value = "/getAllFeatureForReq", method = RequestMethod.GET)
    @ResponseBody
    public Map getAllFeatureForReq( @ApiParam(value = "req id", required = true) @RequestParam(value = "reqId", required = true) String reqId,
                                    @ApiParam(value = "withAttr", required = false) @RequestParam(value = "withAttr", required = false, defaultValue = "0") String withAttr) {

        return this.getRtn("0", "success", this.featureManager.getAllFeatureForReq(reqId,withAttr));
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "req上线")
    @RequestMapping(value = "/operateForReqOnline", method = RequestMethod.GET)
    @ResponseBody
//    @CacheEvict(cacheNames = {"tree_feature"}, allEntries = true)
    @CacheEvict(cacheNames = {"tree_feature"}, allEntries = true)
    public Map operateForReqOnline(@ApiParam(value = "reqIds，上线的reqIds") @RequestParam(value = "reqIds", required = true) String reqIds,
                                   @ApiParam(value = "reqName", required = false) @RequestParam(value = "reqName", required = false) String reqName) {
        ExecuteResult executeResult = new ExecuteResult();
        if (StringUtils.isEmpty(reqIds)) {
            return this.getRtn(executeResult.getCode(), executeResult.getMsg());
        }
        List<String> reqIdLst = Arrays.asList(reqIds.split(","));
        executeResult = this.featureManager.operateFeaturesForReqOnline(reqIdLst, reqName);
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }


    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "req提交feature")
    @RequestMapping(value = "/submit", method = RequestMethod.GET)
    @ResponseBody
//    @CacheEvict(cacheNames = {"tree_feature"}, allEntries = true)
//    @CacheEvict(cacheNames = {"tree_feature"}, allEntries = true)
    public Map submit(@ApiParam(value = "reqId，reqId") @RequestParam(value = "reqId", required = true) String reqId,
                      @ApiParam(value = "featureId，feature id") @RequestParam(value = "featureId", required = true) String featureId,
                      @ApiParam(value = "reqName，reqName") @RequestParam(value = "reqName", required = false) String reqName) {


        ExecuteResult executeResult = null;
        try {
            executeResult = this.featureManager.submit(reqId, featureId, reqName, null);
        }catch (Exception e){
            logger.error(e.getMessage(), e);
            executeResult =  ExecuteResult.getExecuteResult(BaseController.REQUEST_ERROR, e.getMessage(), null);
        }
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }

    @Deprecated
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "解除关联后重置功能点信息")
    @RequestMapping(value = "/initFeature", method = RequestMethod.POST)
    @ResponseBody
    @CacheEvict(cacheNames = {"tree_feature"}, allEntries = true)
    public Map initFeature(
            @ApiParam(value = "功能点id", required = true) @RequestParam(value = "featureId", required = true) String featureId
    ) {
        Map map = this.featureManager.initFeature(featureId);
        return map;
    }

    /**
     * 已使用
     * @param req_id
     * @param feature_id
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取feature的（主）历史版本")
    @RequestMapping(value = "/getFeatureHistory", method = RequestMethod.GET)
    @ResponseBody
    public Map getFeatureHistory( @ApiParam(value = "req_id", required = false) @RequestParam(value = "req_id", required = false) String req_id,
                                  @ApiParam(value = "feature_id", required = true) @RequestParam(value = "feature_id", required = true) String feature_id) {

        return this.getRtn("0", "success", this.featureManager.getFeatureHistory(feature_id, req_id));
    }

    @Deprecated
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取feature的submit历史版本")
    @RequestMapping(value = "/getSubmitHistory", method = RequestMethod.GET)
    @ResponseBody
    public Map getSubmitHistory( @ApiParam(value = "reqId", required = false) @RequestParam(value = "reqId", required = false) String reqId,
                                  @ApiParam(value = "featureId", required = true) @RequestParam(value = "featureId", required = true) String featureId) {

        return this.getRtn("0", "success", this.featureManager.getSubmitHistory(featureId, reqId));
    }




    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取最新提交的feature")
    @RequestMapping(value = "/getLatestSubmitFeature", method = RequestMethod.GET)
    @ResponseBody
    public Map getLatestSubmitFeature( @ApiParam(value = "reqId", required = true) @RequestParam(value = "reqId", required = true) String reqId,
                                 @ApiParam(value = "featureId", required = true) @RequestParam(value = "featureId", required = true) String featureId) {
        ExecuteResult executeResult = this.featureManager.getLatestSubmitFeature(featureId, reqId);
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }


    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取最新版本提交的所有feature")
    @RequestMapping(value = "/getReqLatestSubmitFeatures", method = RequestMethod.GET)
    @ResponseBody
    public Map getReqLatestSubmitFeatures( @ApiParam(value = "reqId", required = true) @RequestParam(value = "reqId", required = true) String reqId) {
        List<Feature> features = null;
        try {
            features = this.featureManager.getReqLatestSubmitFeatures(reqId);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return this.getRtn(BaseController.REQUEST_ERROR, e.getMessage());
        }
        return this.getRtn(BaseController.REQUEST_SUCCESS, "success!", features);
    }

    @RequestMapping(value = "/uploadPrototypeFile", method = RequestMethod.POST, consumes = "multipart/form-data")
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "上传prototype文件", consumes = "multipart/form-data")
    @ResponseBody
    public Map uploadPrototype(@ApiParam(name = "prototype", allowMultiple = true) @RequestParam("prototype") MultipartFile file,
                               @ApiParam(name = "reqId", value = "reqId") @RequestParam("reqId") String reqId,
                               @ApiParam(name = "featureId", value = "featureId") @RequestParam("featureId") String featureId,
                               @ApiParam(name = "version", value = "version, 缺省为当前版本") @RequestParam(value = "version", required = false) String version)  {
        ExecuteResult executeResult = this.featureManager.uploadPrototype(file, reqId, featureId, version);
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }


    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "下载prototype文件")
    @RequestMapping(value = "/getPrototypeFile", method = RequestMethod.GET)
    @ResponseBody
    public void getPrototypeFile(@ApiParam(value = "reqId", required = false) @RequestParam(value = "reqId", required = false) String reqId,
                                @ApiParam(value = "featureId')", required = false) @RequestParam(value = "featureId", required = false) String featureId,
                                @ApiParam(value = "version')", required = false) @RequestParam(value = "version", required = false) String version,
                                 HttpServletRequest request,
                                 HttpServletResponse response) throws Exception {
        File file = this.featureManager.getPrototype(reqId, featureId, version);

        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        String mimeType = URLConnection.guessContentTypeFromName(file.getName());
        if (mimeType == null) {
            mimeType = "application/octet-stream";
        }
        response.setContentType(mimeType);
        response.setHeader("Content-Disposition", new String(("attachment;fileName=" + file.getName()).getBytes("UTF-8"), "ISO-8859-1"));
        try {
            if (!file.exists()) {
                throw new Exception("no file on disk found for this attachment");
            }
            long length = file.length();
            response.setContentLength((int) length);
            InputStream inputStream = new FileInputStream(file);
            OutputStream os = response.getOutputStream();
            byte[] b = new byte[1024];
            int len;
            while ((len = inputStream.read(b)) > 0) {
                os.write(b, 0, len);
            }
            os.close();
            inputStream.close();
        } catch (Exception e) {
            throw e;
        }
    }


    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取所有的menu, page, feature元素")
    @RequestMapping(value = "/getAllElements", method = RequestMethod.GET)
    @ResponseBody
    public Map getAllElements(@ApiParam(value = "sys，所属系统('tom','sellerportal')", required = true) @RequestParam(value = "sys", required = true) String sys){
        ExecuteResult executeResult = this.featureManager.getAllElements(sys.toUpperCase(), true);
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }


    @RequestMapping(value = "/reqSubmit", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "reqSubmit时调用")
    @ResponseBody
    public Map reqSubmit(@ApiParam(value = "reqId", required = true)@RequestParam(value = "reqId", required = true)String reqId,
                         @ApiParam(value = "version", required = false)@RequestParam(value = "version", required = false)String version,
                         @ApiParam(value = "reqName", required = true)@RequestParam(value = "reqName", required = true)String reqName){

        ExecuteResult   executeResult = this.featureManager.reqSubmit(reqId, version, reqName);
        return this.getRtn(executeResult.getCode(), executeResult.getMsg(), executeResult.getData());
    }


    public static class FeatureVersionVo implements Serializable {

        private String featureId;
        private String reqId;
        private String reqName;
        private String version;
        private Map<String, Object> attrs;

        public String getReqName() {
            return reqName;
        }

        public void setReqName(String reqName) {
            this.reqName = reqName;
        }

        public String getFeatureId() {
            return featureId;
        }

        public void setFeatureId(String featureId) {
            this.featureId = featureId;
        }

        public String getReqId() {
            return reqId;
        }

        public void setReqId(String reqId) {
            this.reqId = reqId;
        }

        public String getVersion() {
            return version;
        }

        public void setVersion(String version) {
            this.version = version;
        }

        public Map<String, Object> getAttrs() {
            return attrs;
        }

        public void setAttrs(Map<String, Object> attrs) {
            this.attrs = attrs;
        }
    }

    /**
     * 获得所有的feature version(包括master, req)
     * @return
     */
    @RequestMapping(value = "/getAllFeatureVersions", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "获取feature的版本地图")
    @ResponseBody
    public Map getAllFeatureVersions(@ApiParam(value = "featureId", required = true)@RequestParam(value = "featureId", required = true)String featureId){
        Map<String, Object> result = null;
        try {
            result = this.featureManager.getAllFeatureVersions(featureId);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return this.getRtn(BaseController.REQUEST_ERROR, e.getMessage());
        }
        return this.getRtn(BaseController.REQUEST_SUCCESS, "success!", result);
    }
}
